
# 从 qtpy 库导入 QtGui 模块，用于处理图形相关操作
from qtpy import QtGui
# 从 qtpy 库导入 QtCore 模块，提供核心的非 GUI 功能
from qtpy import QtCore
# 从 src.UI.Canvas.loopBackDrop 模块导入 backDrop 类
from src.UI.Canvas.loopBackDrop import backDrop
# 从 src.Core.PathsRegistry 模块导入 PathsRegistry 类
from src.Core.PathsRegistry import PathsRegistry
# 从 src.UI.Utils.ConvexHull 模块导入 convex_hull 函数
from src.UI.Utils.ConvexHull import convex_hull
# 从 src.UI.Canvas.Painters 模块导入 ConnectionPainter 类
from src.UI.Canvas.Painters import ConnectionPainter


class IConvexHullBackDrop(object):
    """
    Convex hull backdrop routines. Used by for loop and while loop nodes
    凸包背景相关操作类，供 for 循环和 while 循环节点使用
    """

    def __init__(self):
        """
        初始化 IConvexHullBackDrop 类的实例。
        初始化多边形路径、边界坐标、凸包点列表，并创建背景对象。
        """
        # 调用父类的构造函数
        super(IConvexHullBackDrop, self).__init__()
        # 存储凸包的多边形路径
        self.poly = None
        # 凸包区域的左边界坐标
        self.left = 0
        # 凸包区域的上边界坐标
        self.top = 0
        # 凸包区域的右边界坐标
        self.right = 0
        # 凸包区域的下边界坐标
        self.down = 0
        # 存储凸包的点列表
        self.convex_hull = []
        # 创建背景对象，传入当前实例
        self.backDrop = backDrop(self)

    def computeHull(self):
        """
        计算凸包的多边形路径。
        首先获取循环结束节点的路径，然后根据节点的状态和折叠注释情况收集相关点，
        最后计算这些点的凸包并生成多边形路径。
        """
        # 获取名为 "Paired block" 的引脚的数据，存在未解析的特性引用问题
        loopEndNodePath = self.getPinSG("Paired block").getData()
        # 通过路径注册表获取循环结束节点
        loopEndNode = PathsRegistry().getEntity(loopEndNodePath)

        # 如果循环结束节点不存在，将多边形路径置为空并返回
        if loopEndNode is None:
            self.poly = QtGui.QPainterPath()
            return
        # 检查当前是否在折叠注释下，存在未解析的特性引用问题
        if self.isUnderCollapsedComment():
            # 如果在折叠注释下，将最顶层的折叠注释添加到点列表中，存在未解析的特性引用问题
            p = [self.getTopMostOwningCollapsedComment()]
        else:
            # 否则，将当前实例添加到点列表中
            p = [self]
        # 检查循环结束节点的类名是否为 "loopEnd" 且其包装器存在
        if (
            loopEndNode.__class__.__name__ == "loopEnd"
            and loopEndNode.getWrapper() is not None
        ):
            # 获取循环结束节点的 UI 包装器
            uiLoopEnd = loopEndNode.getWrapper()
            # 检查循环结束节点是否在活动图中
            if loopEndNode.isUnderActiveGraph():
                # 检查 UI 包装器是否在折叠注释下
                if uiLoopEnd.isUnderCollapsedComment():
                    # 如果在折叠注释下，将其最顶层的折叠注释添加到点列表中
                    p.append(uiLoopEnd.getTopMostOwningCollapsedComment())
                else:
                    # 否则，将 UI 包装器添加到点列表中
                    p.append(uiLoopEnd)
        else:
            # 如果不满足条件，将多边形路径置为空并返回
            self.poly = QtGui.QPainterPath()
            return

        # 获取循环节点之间的点并添加到点列表中，存在未解析的特性引用问题
        p += self.getBetwenLoopNodes(self)

        # 存储用于计算凸包的点列表
        path = []
        # 重置凸包区域的边界坐标
        self.left = 0
        self.top = 0
        self.right = 0
        self.down = 0
        # 遍历点列表
        for i in p:
            # 获取节点在场景中的位置
            relPos = i.scenePos()
            # 更新凸包区域的左边界坐标
            self.left = min(self.left, relPos.x())
            # 更新凸包区域的上边界坐标
            self.top = max(self.top, relPos.y())
            # 更新凸包区域的右边界坐标
            self.right = max(self.right, relPos.x())
            # 更新凸包区域的下边界坐标
            self.down = min(self.down, relPos.y())
            # 获取节点的宽度和高度
            relSize = QtCore.QPointF(i.getNodeWidth(), i.geometry().height())
            # 将节点的四个角的坐标添加到路径列表中
            path.append((relPos.x() - 5, relPos.y() - 5))
            path.append((relPos.x() + relSize.x() + 5, relPos.y() - 5))
            path.append((relPos.x() + relSize.x() + 5, relPos.y() + relSize.y() + 5))
            path.append((relPos.x() - 5, relPos.y() + relSize.y() + 5))

        # 如果路径列表中的点数量不少于 3 个
        if len(path) >= 3:
            # 计算路径列表中所有点的凸包
            self.convex_hull = convex_hull(path)
            # 清空路径列表
            path = []
            # 遍历凸包的点列表
            for i in self.convex_hull:
                # 将凸包的点转换为 QtCore.QPointF 对象并添加到路径列表中
                path.append(QtCore.QPointF(i[0], i[1]))
            # 使用 ConnectionPainter 类的 roundCornersPath 方法生成带圆角的多边形路径
            self.poly, none = ConnectionPainter.roundCornersPath(path, 6, True)